require 'xcjobs'

xcode_version = `xcodebuild -version`.split("\n").first.scan(/\d+/).join('.')

if xcode_version.start_with?('10')
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPhone X,OS=12.0'
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch Series 4 - 40mm,OS=5.0',
        'name=Apple Watch Series 4 - 44mm,OS=5.0'
      ]
    elsif platform == 'appletvsimulator'
      [ 'name=Apple TV 4K,OS=12.0'
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
elsif xcode_version.start_with?('9.4')
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPhone 7,OS=11.4',
        'name=iPhone 8,OS=11.4',
        'name=iPhone X,OS=11.4'
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch - 38mm,OS=4.0',
        'name=Apple Watch - 42mm,OS=4.0'
      ]
    elsif platform == 'appletvsimulator'
      [ 'name=Apple TV 4K,OS=11.0'
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
elsif xcode_version.start_with?('9')
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPhone 6s Plus,OS=11.0',
        'name=iPhone SE,OS=11.0',
        'name=iPhone 7,OS=11.0',
        'name=iPhone 8,OS=11.0',
        'name=iPhone X,OS=11.0',
        'name=iPad Air 2,OS=11.0',
        'name=iPad Pro (9.7-inch),OS=11.0',
        'name=iPad Pro (12.9-inch),OS=11.0'
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch - 38mm,OS=4.0',
        'name=Apple Watch - 42mm,OS=4.0'
      ]
    elsif platform == 'appletvsimulator'
      [ 'name=Apple TV 1080p,OS=11.0'
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
elsif xcode_version.start_with?('8.3')
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPhone 5,OS=10.3.1',
        'name=iPhone 5s,OS=10.3.1',
        'name=iPhone 6,OS=10.3.1',
        'name=iPhone 6s Plus,OS=10.3.1',
        'name=iPhone SE,OS=10.3.1',
        'name=iPad Air 2,OS=10.3.1',
        'name=iPad Pro (9.7-inch),OS=10.3.1',
        'name=iPad Pro (12.9-inch),OS=10.3.1'
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch - 38mm,OS=3.0',
        'name=Apple Watch - 42mm,OS=3.0'
      ]
    elsif platform == 'appletvsimulator'
      [ 'name=Apple TV 1080p,OS=10.0'
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
elsif xcode_version.start_with?('8.0')
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPhone 5,OS=10.0',
        'name=iPhone 5s,OS=10.0',
        'name=iPhone 6,OS=10.0',
        'name=iPhone 6s Plus,OS=10.0',
        'name=iPhone SE,OS=10.0',
        'name=iPad Air 2,OS=10.0',
        'name=iPad Pro (9.7 inch),OS=10.0',
        'name=iPad Pro (12.9 inch),OS=10.0'
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch - 38mm,OS=3.0',
        'name=Apple Watch - 42mm,OS=3.0'
      ]
    elsif platform == 'appletvsimulator'
      [ 'name=Apple TV 1080p,OS=10.0'
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
elsif xcode_version.start_with?('7.3') || xcode_version.start_with?('7.2')
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPad 2,OS=8.1',
        'name=iPad Air,OS=8.1',
        'name=iPhone 4s,OS=8.1',
        'name=iPhone 4s,OS=8.3',
        'name=iPhone 4s,OS=8.4',
        'name=iPhone 4s,OS=9.0',
        'name=iPhone 4s,OS=9.2',
        'name=iPhone 5,OS=8.1',
        'name=iPhone 5s,OS=8.1',
        'name=iPhone 6,OS=8.1',
        'name=iPhone 6,OS=8.2',
        'name=iPhone 6,OS=8.3',
        'name=iPhone 6,OS=8.4',
        'name=iPhone 6,OS=9.0',
        'name=iPhone 6,OS=9.2',
        'name=iPhone 6 Plus,OS=8.1',
        'name=iPhone 6 Plus,OS=8.2',
        'name=iPhone 6 Plus,OS=8.3',
        'name=iPhone 6 Plus,OS=8.4',
        'name=iPhone 6 Plus,OS=9.0',
        'name=iPhone 6 Plus,OS=9.2'
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch - 38mm,OS=2.0',
        'name=Apple Watch - 42mm,OS=2.0',
        'name=Apple Watch - 38mm,OS=2.1',
        'name=Apple Watch - 42mm,OS=2.1',
      ]
    elsif platform == 'appletvsimulator'
      [ 'name=Apple TV 1080p,OS=9.0',
        'name=Apple TV 1080p,OS=9.1',
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
elsif xcode_version.start_with?('7.1')
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPad 2,OS=8.1',
        'name=iPad Air,OS=8.1',
        'name=iPhone 4s,OS=8.1',
        'name=iPhone 4s,OS=8.3',
        'name=iPhone 4s,OS=8.4',
        'name=iPhone 4s,OS=9.0',
        'name=iPhone 4s,OS=9.1',
        'name=iPhone 5,OS=8.1',
        'name=iPhone 5s,OS=8.1',
        'name=iPhone 6,OS=8.1',
        'name=iPhone 6,OS=8.2',
        'name=iPhone 6,OS=8.3',
        'name=iPhone 6,OS=8.4',
        'name=iPhone 6,OS=9.0',
        'name=iPhone 6,OS=9.1',
        'name=iPhone 6 Plus,OS=8.1',
        'name=iPhone 6 Plus,OS=8.2',
        'name=iPhone 6 Plus,OS=8.3',
        'name=iPhone 6 Plus,OS=8.4',
        'name=iPhone 6 Plus,OS=9.0',
        'name=iPhone 6 Plus,OS=9.1'
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch - 38mm,OS=2.0',
        'name=Apple Watch - 42mm,OS=2.0',
      ]
    elsif platform == 'appletvsimulator'
      [ 'name=Apple TV 1080p,OS=9.0',
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
elsif xcode_version.start_with?('7.0')
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPad 2,OS=8.1',
        'name=iPad Air,OS=8.1',
        'name=iPhone 4s,OS=8.1',
        'name=iPhone 4s,OS=8.3',
        'name=iPhone 4s,OS=8.4',
        'name=iPhone 4s,OS=9.0',
        'name=iPhone 5,OS=8.1',
        'name=iPhone 5s,OS=8.1',
        'name=iPhone 6,OS=8.1',
        'name=iPhone 6,OS=8.2',
        'name=iPhone 6,OS=8.3',
        'name=iPhone 6,OS=8.4',
        'name=iPhone 6,OS=9.0',
        'name=iPhone 6 Plus,OS=8.1',
        'name=iPhone 6 Plus,OS=8.2',
        'name=iPhone 6 Plus,OS=8.3',
        'name=iPhone 6 Plus,OS=8.4',
        'name=iPhone 6 Plus,OS=9.0',
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch - 38mm,OS=2.0',
        'name=Apple Watch - 42mm,OS=2.0',
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
else
  def destinations(platform: 'iphonesimulator')
    if platform == 'iphonesimulator'
      [ 'name=iPad 2,OS=8.1',
        'name=iPad Air,OS=8.1',
        'name=iPhone 4s,OS=8.1',
        'name=iPhone 4s,OS=8.4',
        'name=iPhone 5,OS=8.1',
        'name=iPhone 5s,OS=8.1',
        'name=iPhone 6,OS=8.1',
        'name=iPhone 6,OS=8.2',
        'name=iPhone 6,OS=8.4',
        'name=iPhone 6 Plus,OS=8.1',
        'name=iPhone 6 Plus,OS=8.2',
        'name=iPhone 6 Plus,OS=8.4',
      ]
    elsif platform == 'watchsimulator'
      [ 'name=Apple Watch - 38mm,OS=2.0',
        'name=Apple Watch - 42mm,OS=2.0',
      ]
    else
      [
        'platform=OS X,arch=x86_64'
      ]
    end
  end
end

def schemes
  ['UICKeyChainStore', 'libUICKeyChainStore']
end

if xcode_version.start_with?('7.0')
  def supportedPlatforms
    ['macosx', 'iphoneos', 'iphonesimulator', 'watchos', 'watchsimulator']
  end
elsif xcode_version.start_with?('6')
  def supportedPlatforms
    ['macosx', 'iphoneos', 'iphonesimulator']
  end
else
  def supportedPlatforms
    ['macosx', 'iphoneos', 'iphonesimulator', 'watchos', 'watchsimulator', 'appletvos', 'appletvsimulator']
  end
end

def configurations
  ['Debug', 'Release']
end

desc "build for all platforms"
task :build do |t|
  supportedPlatforms
    .product(configurations)
    .map { |platform, configuration| Rake::Task["build:#{platform}:#{configuration.downcase}"] }
    .map(&:invoke)
end

namespace :build do
  schemes.each do |scheme|
    supportedPlatforms.product(configurations).each do |platform, configuration|
      XCJobs::Build.new("#{platform}:#{configuration.downcase}") do |t|
        t.project = 'UICKeyChainStore'
        t.scheme = scheme
        t.sdk = platform
        t.configuration = configuration
        if xcode_version.start_with?('10')
          if platform == 'iphonesimulator'
            t.add_destination('name=iPhone X,OS=12.0')
          elsif platform == 'watchsimulator'
            t.add_destination('name=Apple Watch Series 4 - 44mm,OS=5.0')
          elsif platform == 'appletvsimulator'
            t.add_destination('name=Apple TV 4K,OS=12.0')
          end
        elsif xcode_version.start_with?('9.4')
          if platform == 'iphonesimulator'
            t.add_destination('name=iPhone 7,OS=11.4')
          elsif platform == 'watchsimulator'
            t.add_destination('name=Apple Watch - 42mm,OS=3.2')
          elsif platform == 'appletvsimulator'
            t.add_destination('name=Apple TV 4K,OS=11.0')
          end
        elsif xcode_version.start_with?('9.0')
          if platform == 'iphonesimulator'
            t.add_destination('name=iPhone 6,OS=11.0')
          elsif platform == 'watchsimulator'
            t.add_destination('name=Apple Watch - 42mm,OS=3.1')
          elsif platform == 'appletvsimulator'
            t.add_destination('name=Apple TV 1080p,OS=11.0')
          end
        elsif xcode_version.start_with?('8.0')
          if platform == 'iphonesimulator'
            t.add_destination('name=iPhone 6,OS=10.0')
          elsif platform == 'watchsimulator'
            t.add_destination('name=Apple Watch - 42mm,OS=3.0')
          elsif platform == 'appletvsimulator'
            t.add_destination('name=Apple TV 1080p,OS=10.0')
          end
        elsif xcode_version.start_with?('7.3') || xcode_version.start_with?('7.2')
          if platform == 'iphonesimulator'
            t.add_destination('name=iPhone 6,OS=9.2')
          elsif platform == 'watchsimulator'
            t.add_destination('name=Apple Watch - 42mm,OS=2.1')
          elsif platform == 'appletvsimulator'
            t.add_destination('name=Apple TV 1080p,OS=9.1')
          end
        end
        t.build_dir = 'build'
        t.hide_shell_script_environment = true
        t.formatter = 'xcpretty -c'
        if ENV['CI']
          t.add_build_setting('CODE_SIGN_IDENTITY', '')
          t.add_build_setting('CODE_SIGNING_REQUIRED', 'NO')
        end
      end
    end
  end
end

namespace :test do
  supportedPlatforms
    .select { |platform| platform == 'macosx' || platform == 'iphonesimulator' || platform == 'appletvsimulator' }
    .each do |platform|
      task platform do |t|
        configurations.each do |configuration|
          destinations(platform: platform)
            .map { |destination| Rake::Task["test:#{platform}:#{configuration.downcase}:#{destination}"] }
            .map(&:invoke)
        end
      end
    end
end

namespace :test do
  supportedPlatforms
    .select { |platform| platform == 'macosx' || platform == 'iphonesimulator' || platform == 'appletvsimulator' }
    .product(configurations)
    .each do |platform, configuration|
      destinations(platform: platform).each do |destination|
        XCJobs::Test.new("#{platform}:#{configuration.downcase}:#{destination}") do |t|
          t.project = 'UICKeyChainStore'
          t.scheme = 'UICKeyChainStore'
          t.sdk = platform
          t.configuration = configuration
          t.add_destination(destination)
          t.coverage = true
          t.build_dir = 'build'
          t.hide_shell_script_environment = true
          t.after_action do
            build_coverage_reports()
            puts `curl -L https://codecov.io/bash | bash -s -- -f 'coverage.txt'`
          end
        end
      end
    end
end

def build_coverage_reports()
  project_name = 'UICKeyChainStore'
  profdata = Dir.glob(File.join('build', '/**/Coverage.profdata')).first
  Dir.glob(File.join('build', "/**/#{project_name}")) do |target|
    output = `xcrun llvm-cov report -instr-profile "#{profdata}" "#{target}" -arch=x86_64`
    if $?.success?
      puts output
      `xcrun llvm-cov show -instr-profile "#{profdata}" "#{target}" -arch=x86_64 -use-color=0 > coverage.txt`
      break
    end
  end
end
